arm64: add kernel config option to set securelevel when in Secure Boot mode
authorLinn Crosetto <linn@hpe.com>
Tue, 30 Aug 2016 17:54:38 +0000 (11:54 -0600)
committerBen Hutchings <ben@decadent.org.uk>
Wed, 4 Jan 2017 19:39:36 +0000 (19:39 +0000)
Add a kernel configuration option to enable securelevel, to restrict
userspace's ability to modify the running kernel when UEFI Secure Boot is
enabled. Based on the x86 patch by Matthew Garrett.

Determine the state of Secure Boot in the EFI stub and pass this to the
kernel using the FDT.

Signed-off-by: Linn Crosetto <linn@hpe.com>
Gbp-Pq: Topic features/all/securelevel
Gbp-Pq: Name arm64-add-kernel-config-option-to-set-securelevel-wh.patch

arch/arm64/Kconfig
drivers/firmware/efi/arm-init.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/fdt.c
include/linux/efi.h

index bc3f00f586f1111fa41c5e36d6530569f0a5b3a8..49008b9590aeb8dd784c14b9e8a31d5d739bc738 100644 (file)
@@ -972,6 +972,19 @@ config EFI
          allow the kernel to be booted as an EFI application. This
          is only useful on systems that have UEFI firmware.
 
+config EFI_SECURE_BOOT_SECURELEVEL
+       def_bool n
+       depends on SECURITY_SECURELEVEL
+       depends on EFI
+       prompt "Automatically set securelevel when UEFI Secure Boot is enabled"
+       ---help---
+         UEFI Secure Boot provides a mechanism for ensuring that the
+         firmware will only load signed bootloaders and kernels. Certain
+         use cases may also require that the kernel restrict any userspace
+         mechanism that could insert untrusted code into the kernel.
+         Say Y here to automatically enable securelevel enforcement
+         when a system boots with UEFI Secure Boot enabled.
+
 config DMI
        bool "Enable support for SMBIOS (DMI) tables"
        depends on EFI
index c49d50e68aeebb0dbe368f8e8f526b8c18bdebb0..df57f6af8bc1bdbfd3e5a0b840d55559b4a6334e 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/of_fdt.h>
 #include <linux/platform_device.h>
 #include <linux/screen_info.h>
+#include <linux/security.h>
 
 #include <asm/efi.h>
 
@@ -243,6 +244,12 @@ void __init efi_init(void)
             "Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
              efi.memmap.desc_version);
 
+#ifdef CONFIG_EFI_SECURE_BOOT_SECURELEVEL
+       if (params.secure_boot > 0) {
+               set_securelevel(1);
+       }
+#endif
+
        if (uefi_init() < 0)
                return;
 
index 7dd2e2d372317f8a4ddb1fe464b29f662a001a28..87e7db08ac2a438e153190c881ce104207c00b8d 100644 (file)
@@ -580,7 +580,8 @@ static __initdata struct params fdt_params[] = {
        UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
        UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
        UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
-       UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
+       UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver),
+       UEFI_PARAM("Secure Boot Enabled", "linux,uefi-secure-boot", secure_boot)
 };
 
 static __initdata struct params xen_fdt_params[] = {
index d1cb612ecbc9edb0fea4bc624a9c9ca754b02490..61ad972f0f8b0e57b9e74395f8ac2286e48130ce 100644 (file)
@@ -20,7 +20,7 @@
 
 bool __nokaslr;
 
-static int efi_get_secureboot(efi_system_table_t *sys_table_arg)
+int efi_get_secureboot(efi_system_table_t *sys_table_arg)
 {
        static efi_char16_t const sb_var_name[] = {
                'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 };
index ee49cd23ee636d96b7d340ee74577ff8aef50822..97a329a7c25284fdec2fb58b5e41b83b3e2b097f 100644 (file)
@@ -62,4 +62,5 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
 
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
 
+int efi_get_secureboot(efi_system_table_t *sys_table_arg);
 #endif
index a6a93116a8f053f6c14911376ffa6da7f1dff44e..dc786dcdb3dd369d0b1549dcf57550ff8568ad5b 100644 (file)
@@ -139,6 +139,13 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
                        return efi_status;
                }
        }
+
+       fdt_val32 = cpu_to_fdt32(efi_get_secureboot(sys_table));
+       status = fdt_setprop(fdt, node, "linux,uefi-secure-boot",
+                            &fdt_val32, sizeof(fdt_val32));
+       if (status)
+               goto fdt_set_fail;
+
        return EFI_SUCCESS;
 
 fdt_set_fail:
index 7c299443c71dc75f8ef5150e4efd37dbe8db3465..a0ea5ebccbd2f1bafd16b2af9f25a3c7e21d789a 100644 (file)
@@ -696,6 +696,7 @@ struct efi_fdt_params {
        u32 mmap_size;
        u32 desc_size;
        u32 desc_ver;
+       u32 secure_boot;
 };
 
 typedef struct {